#include <cupeLKT4201.h>
#include <stm32f1xx_hal_smartcard.h>

// 设置USART3为智能卡模式(PC10_TX PC11_RX PC12_CK)
SMARTCARD_HandleTypeDef hsc3;

// Call by HAL_SMARTCARD_Init()
void HAL_SMARTCARD_MspInit(SMARTCARD_HandleTypeDef *hsc)
{
  if(hsc->Instance == USART3)
  {
    // 使能GPIOC时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();
    // 使能AFIO时钟
    __HAL_RCC_AFIO_CLK_ENABLE();
    // 使能串口时钟
    __HAL_RCC_USART3_CLK_ENABLE();

    // 将USART3部分映射到PC10_TX PC11_RX PC12_CK
    __HAL_AFIO_REMAP_USART3_PARTIAL();

    GPIO_InitTypeDef GPIO_InitStruct; // = {0};

    // 配置PC10为复用推挽输出模式
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    // 配置PC12为复用推挽输出模式
    GPIO_InitStruct.Pin = GPIO_PIN_12;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    // 配置PC11为浮空输入模式
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  }
}

void MX_SMARTCARD_Init(SMARTCARD_HandleTypeDef *hsc)
{
  // 加密芯片采用 1 起始位、8 数据位（低位在前，高位在后）、1 偶校验位、2 停止位的帧格式。
  // 当外部时钟频率为3.579545MHz时，默认通讯速率约等于9600bps。
  hsc->Instance = USART3;
  hsc->Init.BaudRate = 9600;
  hsc->Init.WordLength = SMARTCARD_WORDLENGTH_9B;
  hsc->Init.StopBits = UART_STOPBITS_2;
  hsc->Init.Mode = SMARTCARD_MODE_TX_RX;
  hsc->Init.Parity = UART_PARITY_EVEN;
  // 时钟分频因子(APB1时钟为36M, 5*2 = 10分频，36M/10 = 3.6M)
  hsc->Init.Prescaler = 5;
  hsc->Init.GuardTime = 16;
  hsc->Init.NACKState = SMARTCARD_NACK_ENABLE;
  if (HAL_SMARTCARD_Init(hsc) != HAL_OK)
  {
    Error_Handler();
  }

}

// 接收响应数据并打印
void print_response(const char *msg, int len)
{
  uint8_t *dst = (uint8_t *)malloc(len);
  memset(dst, 0, len);
  if (HAL_SMARTCARD_Receive(&hsc3, dst, len, 500) == HAL_OK)
  {
    dbLog("\n%s ", msg);
    for (int i = 0; i < len; i++)
    {
      dbLog("%02X ", dst[i]);
    }
  }
  else
  {
    dbLog("\nNo response!", msg);
  }

  free(dst);
}

void LKT::init()
{
  MX_SMARTCARD_Init(&hsc3);

  pinMode(PC13, OUTPUT);
  // 复位(测试有响应，但数据似乎不对)
  digitalWrite(PC13, HIGH);
  print_response("Cold reset: ", 18);

  delay(20);
  digitalWrite(PC13, LOW);
  delay(10);
  digitalWrite(PC13, HIGH);
  // 热复位(测试有响应，但数据似乎不对)
  print_response("Hot reset: ", 18);

  delay(500);
  // 读取随机数(测试没有响应)
  uint8_t src[] = {0x00, 0x84, 0x00, 0x00, 0x08};
  if (HAL_SMARTCARD_Transmit(&hsc3, src, 5, 1000) == HAL_OK)
  {
    delay(10);
    print_response("Random number: ", 8);
  }
  else
  {
    dbLog("\nSend error!");
  }
}
